﻿using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;

public class ActionBase{

    private int tag_ = 0;
    public int Tag {
        set { this.tag_ = value; }
        get { return this.tag_; }
    }
    public virtual int Update(float dt) { return -1; }
    public bool IsInActions = false;

    public virtual void Dispose() { }
}

public class ActionDurition : ActionBase
{
    protected float durtion_ = 0;
}

public class ActionShake : ActionDurition
{
    private Transform target_ = null;
    private float volume_ = 0;
    private Vector2 oriPos_ = Vector2.zero;
    public ActionShake(Transform target,float volume,float durition) {
        target_ = target;
        volume_ = volume;
        this.oriPos_ = target_.localPosition;
        this.durtion_ = durition;
    }

    public override void Dispose() {
        target_.localPosition = this.oriPos_;
        target_ = null;
    }
    public override int Update(float dt)
    {
        this.durtion_ = this.durtion_ - dt;
        if (this.durtion_<=0) {
            this.target_.localPosition = new Vector3(
                this.oriPos_.x ,
                this.oriPos_.y ,
                this.target_.localPosition.z);
            return -1;
        } else {
            float seed1 = UnityEngine.Random.Range(0, 10);
            float seed2 = UnityEngine.Random.Range(0, 10);

            float xd = (seed1 - 5.0f)/10.0f;
            float yd = (seed2 - 5.0f) /10.0f;
            var ori = new Vector2(xd,yd);

            ori = ori.normalized;
            ori = new Vector2(ori.x*this.volume_,ori.y*this.volume_);
            this.target_.localPosition = new Vector3(
                this.oriPos_.x+ori.x,
                this.oriPos_.y+ori.y,
                this.target_.localPosition.z);
            return 1;
        }
        
    }

}


public interface IBackFirer {
     void SetHorizonVec(float x);
     float GetHorizonVec();
}
public class ActionBackFire : ActionDurition
{

    private IBackFirer bf_;
    private float lp_;
    private float startHori_;
    private float OriBFV_;
    public ActionBackFire(IBackFirer bf,float durition,float lerp,float startHori) {
        this.bf_ = bf;
        this.durtion_ = durition;
        this.lp_ = lerp;
        this.startHori_ = startHori;
        this.bf_.SetHorizonVec(this.startHori_);
    }
    public override int Update(float dt)
    {
        this.durtion_ = this.durtion_ - dt;
        if (this.durtion_ <= 0)
        {
            this.bf_.SetHorizonVec(0);
            return -1;
        }
        else
        {
            this.bf_.SetHorizonVec(Mathf.Lerp(this.bf_.GetHorizonVec(), 0, this.lp_));
            return 1;
        }
    }
    public override void Dispose()
    {
        this.bf_.SetHorizonVec(0);
        this.bf_ = null;
    }

}

public interface ISparker {
    void TurnNormal();
    void TurnSpark();
}

public class ActionSpark :ActionDurition {
    private bool isNowNormal_ = true;
    private float fq_ = 0;
    private float sparkTimeStamp_ = 0;
    private float clock_ = 0;
    private ISparker sparker_ = null;
    public ActionSpark(ISparker bf, float durition,float fq) {
        this.sparker_ = bf;
        this.fq_ = fq;
        this.durtion_ = durition;
    }

    private void spark() {
        if (this.isNowNormal_)
        {
            this.sparker_.TurnSpark();
            this.isNowNormal_ = false;
        }
        else {
            this.sparker_.TurnNormal();
            this.isNowNormal_ = true;
        }
    }
    public override int Update(float dt)
    {
        this.clock_ = this.clock_ + dt;
        this.durtion_ = this.durtion_ - dt;
        if (this.durtion_ <= 0)
        {
            this.sparker_.TurnNormal();
            return -1;
        }
        else
        {
            if (this.clock_ - this.sparkTimeStamp_>this.fq_) {
                this.spark();
                this.sparkTimeStamp_ = this.clock_;
            }   
            return 1;
        }
    }

    public override void Dispose()
    {
        this.sparker_.TurnNormal();
    }
}



public interface ICreate {
    void Create();
}
public class ActionCreateEnemy : ActionBase {

    private ICreate ic_ = null;
    private int createTimes_ = 0;
    private float fq_ = 0;

    private float addTime_ = 0;

    public ActionCreateEnemy(ICreate ic, int createTimes,float fq){
        this.ic_ = ic;
        this.createTimes_ = createTimes;
        this.fq_ = fq;
    }
    public override int Update(float dt)
    {
        addTime_ = addTime_ + dt;
        if (addTime_ > this.fq_) {
            if (this.createTimes_ > 0)
            {
                this.ic_.Create();
                this.createTimes_ = this.createTimes_ - 1;
                this.addTime_ = 0;
                return 1;
            }
            else {
                return -1;
            }
        }
        return 1;
    }

    public override void Dispose()
    {
        ic_ = null;
    }
}

public class ActionProcesser : MonoBehaviour
{
    private List<ActionBase> listOfactions_ = new List<ActionBase>();

    // Update is called once per frame
    void Update()
    {
        var count = listOfactions_.Count;
        for (var i = count -1;i>=0;--i) {
            var result = listOfactions_[i].Update(Time.deltaTime);
            if (result == -1) {
                listOfactions_.RemoveAt(i);
            }
        }
    }

    public void RunAction(ActionBase a, int tag = 0) {
        if (a.IsInActions == false) {
            a.Tag = tag;
            this.listOfactions_.Add(a);
            a.IsInActions = true;
        }
    }

    public void StopAllActions() {
        for (var i = 0;i<this.listOfactions_.Count;++i) {
            this.listOfactions_[i].Dispose();
        }
        this.listOfactions_.Clear();
    }

    public void StopActionByTag(int tag) {
        for (var i = this.listOfactions_.Count -1;i>=0;--i) {
            var item = this.listOfactions_[i];
            if (item.Tag == tag) {
                this.listOfactions_.RemoveAt(i);
                item.Dispose();
            }
        }
    }



    public int ActionsCount() {
        return this.listOfactions_.Count;
    }
}
